//TODO: RaiseToPower, AddParameters
using System;
using System.Drawing;
using System.Drawing.Imaging;

namespace LowLevelGraphics.Filter
{
    /// <summary>
    /// Exponential is an algorithm to raise to power an image
    /// </summary>
    public class RaiseToPower : BaseImageFilter
    {
        protected double m_dExponent = 1.0f;

        /// <summary>
        /// Initializes a new instance of the <see cref="RaiseToPower"/> class.
        /// </summary>
        public RaiseToPower()
        {
        }

        /// <summary>
        /// This is the filter constructor you would normally use
        /// </summary>
        /// <param name="_dExponent">The _d exponent.</param>
        /// <param name="_fScaleVal">The _f scale val.</param>
        /// <param name="_fOffsetVal">The _f offset val.</param>
        public RaiseToPower(double _dExponent, float _fScaleVal, float _fOffsetVal)
        {
            m_dExponent = _dExponent;
            m_fScale = _fScaleVal;
            m_fOffset = _fOffsetVal;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="RaiseToPower"/> class.
        /// </summary>
        /// <param name="_raiseToPower">The _raise to power.</param>
        internal RaiseToPower(RaiseToPower _raiseToPower)
        {
            this.m_dExponent = _raiseToPower.m_dExponent;
        }

        /// <summary>
        /// Gets or sets the exponent.
        /// </summary>
        /// <value>The exponent.</value>
        public double Exponent
        {
            get { return m_dExponent; }
            set { m_dExponent = value; }
        }

        /// <summary>
        /// Execute this filter
        /// </summary>
        /// <param name="_bitmap"></param>
        public override UnsafeBitmap Execute(UnsafeBitmap _bitmap)
        {
            ApplyRaise(_bitmap,m_dExponent, m_fScale, m_fOffset);
            return _bitmap;
        }
    
        /// <summary>
        /// apply_raise applies a power operator to an image
        /// Tim's exponential algorithm..
        ///  a) assume the image is grey level (hence RR=GG=BB)
        ///  b) use value <!-- &0x000000ff to get the BB value -->
        ///  c) apply the operation (eg exponentiate). 
        ///  d) return the result
        /// </summary>
        /// <param name="_bitmap">The source image as a pixel array</param>
        /// <param name="expo">The exponential scaling factor</param>
        /// <param name="scaleval">The scaling factor to be applied</param>
        /// <param name="offsetval">The offset value to be added</param>
        private void ApplyRaise(UnsafeBitmap _bitmap, double expo,
                     float scaleval, float offsetval)
        {
            UnsafeBitmap bitmap = _bitmap;
            int src_rgb;
            int result = 0;

            int nHeight = bitmap.Height;
            int nWidth = bitmap.Width;

            for (int y = 0; y < nHeight; y++)
            {
                for (int x = 0; x < nWidth; x++)
                {
                    Color color = bitmap.GetPixel(x, y);
                    int nValue = color.ToArgb();
                    //Select required bits from image
                    src_rgb = nValue & 0x000000ff;

                    //Perform operation
                    result = (int)(Math.Pow(src_rgb, expo));
                    result = (int)((result * scaleval) + offsetval);
                    if (result > 255) result = 255;
                    if (result < 0) result = 0;

                    int nColorResult = (int)(0xFF << 24 | result << 16 | result << 8 | result);
                    bitmap.SetPixel(x,y, Color.FromArgb(nColorResult));
                }
            }
            bitmap.Dispose();
        }

        /// <summary>
        /// This is used to clone a filter, each filter must implement it's own clone functionality
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new RaiseToPower(this);
        }
    }
}
  
